package master.ghrm.domain;

import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Version;

import org.apache.commons.collections.CollectionUtils;

/**
 * Evaluation Question
 */
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Question extends AbstractBaseEntity {

	private static final long serialVersionUID = 1L;

	private static final String[] EXCL_ATTR = { "version", "evalCategory" };

	public static final int LENGTH_TEXT = 1000;
	public static final int LENGTH_NAME = 80;

	@Version
	private Long version;

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	@Column(name = "question_id")
	private Integer questionId;

	@Column(nullable = false, length = LENGTH_NAME)
	private String name;

	private String subject;

	@Column(nullable = false, length = LENGTH_TEXT)
	private String text;

	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "eval_category_id")
	private EvalCategory evalCategory;

	@Column(name = "must_be_answered")
	private Boolean mustBeAnswered;

	@Column(name = "needs_elaboration")
	private boolean needsElaboration;

	@ManyToOne(cascade = { CascadeType.PERSIST, CascadeType.MERGE }, fetch = FetchType.EAGER, targetEntity = EvaluationQuestionType.class)
	@JoinColumn(name = "question_type_id", nullable = false)
	private EvaluationQuestionType questionType;

	/**
	 * Default constructor, persistence use.
	 */
	public Question() {
		this.mustBeAnswered = Boolean.FALSE;
		this.questionType = new EvaluationQuestionType();
	}

	/**
	 * @param aName name.
	 * @param aText text.
	 */
	public Question(String aName, String aText) {
		this.name = aName;
		this.text = aText;
		this.mustBeAnswered = Boolean.FALSE;
		this.questionType = new EvaluationQuestionType();
	}

	/**
	 * 
	 * @param aName name.
	 * @param text text.
	 * @param isMandatoryAnswer if question must be answered.
	 */
	public Question(String aName, String aText, Boolean isMandatoryAnswer) {
		this.name = aName;
		this.text = aText;
		this.mustBeAnswered = isMandatoryAnswer;
		this.questionType = new EvaluationQuestionType();
	}

	/**
	 * @return ID.
	 */
	public Integer getQuestionId() {
		return this.questionId;
	}

	/**
	 * @param aQuestionId ID.
	 */
	public void setQuestionId(Integer aQuestionId) {
		this.questionId = aQuestionId;
	}

	/**
	 * @return the version
	 */
	public Long getVersion() {
		return this.version;
	}

	/**
	 * @param aVersion the version to set
	 */
	void setVersion(Long aVersion) {
		this.version = aVersion;
	}

	/**
	 * @return name.
	 */
	public String getName() {
		return this.name;
	}

	/**
	 * @param aName name.
	 */
	public void setName(String aName) {
		this.name = aName;
	}

	/**
	 * @return text.
	 */
	public String getText() {
		return this.text;
	}

	/**
	 * @param aText text.
	 */
	public void setText(String aText) {
		this.text = aText;
	}

	/**
	 * @return question category.
	 */
	public EvalCategory getEvalCategory() {
		return this.evalCategory;
	}

	/**
	 * @param anEvalCategory category
	 */
	public void setEvalCategory(EvalCategory anEvalCategory) {
		this.evalCategory = anEvalCategory;
	}

	/**
	 * @return does question must be answered
	 */
	public Boolean getMustBeAnswered() {
		return this.mustBeAnswered;
	}

	/**
	 * @param isMandatoryAnswer if the question must be answered
	 */
	public void setMustBeAnswered(Boolean isMandatoryAnswer) {
		this.mustBeAnswered = isMandatoryAnswer;
	}

	/**
	 * @return the questionType
	 */
	public EvaluationQuestionType getQuestionType() {
		return this.questionType;
	}

	/**
	 * @param aQuestionType the questionType to set
	 */
	public void setQuestionType(EvaluationQuestionType aQuestionType) {
		this.questionType = aQuestionType;
	}

	/**
	 * @return the needsElaboration
	 */
	public boolean isNeedsElaboration() {
		return needsElaboration;
	}

	/**
	 * @param doesNeedElaboration if needs elaboration
	 */
	public void setNeedsElaboration(boolean doesNeedElaboration) {
		this.needsElaboration = doesNeedElaboration;
	}

	public Boolean isLocked() {
		Boolean isLocked = Boolean.FALSE;

		List<Questioneer> questioneers = evalCategory.getQuestioneers();
		if (CollectionUtils.isNotEmpty(questioneers)) {
			for (Questioneer questioneer : questioneers) {
//				List<Evaluation> evaluations = questioneer.getEvaluations();
//				if (CollectionUtils.isNotEmpty(evaluations)) {
//					for (Evaluation evaluation : evaluations) {
//						isLocked = evaluation.getPublished();
//
//						if (isLocked) {
//							break;
//						}
//					}
//				}

				if (isLocked) {
					break;
				}
			}
		}

		return isLocked;
	}

	/**
	 * @return array of additional attributes to exclude.
	 */
	protected abstract String[] getAdditionalExclAttr();

	/**
	 * Concatenate base exclude attributes and additional ones.
	 * 
	 * @return complete array of exclude attributes.
	 * @see #getAdditionalExclAttr()
	 */
	@Override
	protected String[] getExcludedAttributes() {
		String[] additional = getAdditionalExclAttr();
		if (additional == null || additional.length == 0) {
			return EXCL_ATTR;
		}
		String[] result = new String[EXCL_ATTR.length + additional.length];
		for (int i = 0; i < EXCL_ATTR.length; ++i) {
			result[i] = EXCL_ATTR[i];
		}
		for (int i = 0; i < additional.length; ++i) {
			result[EXCL_ATTR.length + i] = additional[i];
		}
		return result;
	}

	public void setSubject(String aSubject) {
		this.subject = aSubject;
	}

	public String getSubject() {
		return subject;
	}
}
